//Classes here should not explore outside except eutranManager
#ifndef _EUTRANCTRL_H_
#define _EUTRANCTRL_H_
#include "NmmToX86Protocol.h"
#include "eutranManager.h"
#include "BbuManager.h"
#include <vector>
#include <map>
#include <list>
#include <set>
#ifdef abandon
class SnifferManager;

class SnifferState
{
public:
    SnifferState();
    virtual bool processStartCommand(const std::vector<EarfcnRangeType>& range, const std::vector<uint16_t>* pciList=NULL) = 0;
    virtual bool processStartRspMessage(const NmmToX86Protocol_SnifferStartRsp& rsp, in_addr_t peerAddr) = 0;
    virtual bool processStopCommand() = 0;
    virtual bool processResetCommand() = 0;
    virtual bool processRequestStatusCommand() = 0;
    virtual bool processRssiConfigCommand(uint16_t rssi) = 0;
    virtual bool processCellConfigCommand() = 0;

    virtual ~SnifferState()
    {
    };

};

class SnifferIdleState : public SnifferState
{
public:

    SnifferIdleState();
    static SnifferIdleState* instance();
    virtual ~SnifferIdleState()
    {
    };
    virtual bool processStartCommand(const std::vector<EarfcnRangeType>& range, const std::vector<uint16_t>* pciList=NULL);
    virtual bool processStartRspMessage(const NmmToX86Protocol_SnifferStartRsp& rsp, in_addr_t peerAddr); 
    virtual bool processStopCommand();
    virtual bool processResetCommand();
    virtual bool processRequestStatusCommand();
    virtual bool processRssiConfigCommand(uint16_t rssi);
    virtual bool processCellConfigCommand();
};

class SnifferMeasuringState : public SnifferIdleState
{
public:
    SnifferMeasuringState();
    static SnifferMeasuringState* instance();
    virtual ~SnifferMeasuringState()
    {
    };

    virtual bool processStartCommand(const std::vector<EarfcnRangeType>& range, const std::vector<uint16_t>* pciList=NULL);
    virtual bool processStartRspMessage(const NmmToX86Protocol_SnifferStartRsp& rsp, in_addr_t peerAddr);
    virtual bool processStopCommand();
};
#endif
class EarfcnCapacity
{
public:
    static const uint32_t BAND9 = 0x0001;
    static const uint32_t BAND38 = 0x0002;
    static const uint32_t BAND39 = 0x0004;
    static const uint32_t BAND40 = 0x0008;
    static const uint32_t MIN_BAND_MASK = BAND9;
    static const uint32_t MAX_BAND_MASK = BAND40;

    EarfcnCapacity(uint32_t mask);
    bool isBandSupported(uint32_t mask);

    static bool getEarfcnRangeFromBand(uint8_t band, uint16_t& lowerArfcn, uint16_t& upperArfcn);

    inline static uint8_t getBandFromEarfcn(uint16_t earfcn)
    {
        return bandTable_[earfcn];
    }

    inline static uint32_t getBandMaskCodeFromEarfcn(uint16_t earfcn)
    {
        if( bandTable_[earfcn]==9 )
        {
            return BAND9;
        }
        else if( bandTable_[earfcn]==38 )
        {
            return BAND38;
        }
        else if( bandTable_[earfcn]==39 )
        {
            return BAND39;
        }
        else if( bandTable_[earfcn]==40 )
        {
            return BAND40;
        }
        return 0;
    }
    
    inline bool operator==(const EarfcnCapacity& other)
    {
        if( this->capacities_==other.capacities_ )
        {
            return true;
        }
        return false;
    }

    inline uint32_t getCapacity()
    {
        return capacities_;
    }
private:
    uint32_t capacities_; 
    static uint8_t bandTable_[65536];
};
#ifdef abandon
class SnifferInstance
{
public:
    bool startSniffer(const std::vector<EarfcnRangeType>& range, const std::vector<uint16_t>* pciList=NULL);
    void stopSniffer();
    void resetSnifferResult();
    void requestSnifferStatus();
    void configRssiThresold(uint16_t rssi);
    bool configCell();

    bool isFddMode();

    bool sendMessageToEpcSim(uint8_t* msgBuf, uint32_t msgSize);

    void handleHearBeatAck();

    uint32_t getSeqNumber();

    uint8_t getSlotId();
    bool isActive();

    bool isBandSupport(EarfcnCapacity);
private:
    LteDuplexMode supportMode_;
    bool isActive_;
    ChinaTelecomOperator operator_;
    uint16_t slot_;
    EarfcnCapacity bandSupported_;
    struct sockaddr_in peerAddr_;
    int32_t fd_;
    bool isHearBeatAckReceived_;
    uint32_t seqNo_;

    friend class SnifferManager;
    SnifferInstance(const char* address, LteDuplexMode ltemode, int slot, EarfcnCapacity cap, ChinaTelecomOperator mpoperator);
    SnifferInstance(const SnifferInstance&);
    SnifferInstance& operator=(const SnifferInstance&);
    bool initialize();
};


class SnifferManager
{
public:
    static SnifferManager* instance();
    bool processStartSnifferMessage(const std::vector<EarfcnRangeType>& range, const std::vector<uint16_t>* pciList=NULL);
    bool processStopSnifferReq();
    bool processEpcSimMessage(uint8_t* msgBuf, uint32_t bufSize, in_addr_t peerAddr);
    bool isSniffering();
    uint16_t getRssiThresold();
    uint8_t getRptStrategy();
    void sendHearBeat();
    void indicateCheckAliveTimeout();
    void resetSnifferResults();
    void resetSniffer();
    void resetAllSnifferInstances();
    void resetSnifferInstance(uint8_t slotId);
    void saveRssiThreshold(uint16_t rssi);

    bool isAutoCfgCell();
    SnifferManager* setIsAutoCfgCell(bool isCfg);

    void test();

private:
    SnifferManager();
    SnifferManager(const SnifferManager&);
    SnifferManager& operator=(const SnifferManager&);

    friend class SnifferIdleState;
    friend class SnifferMeasuringState;
    friend class EutranManager;
    bool startSniffer(const std::vector<EarfcnRangeType>& range, const std::vector<uint16_t>* pciList=NULL);
    bool startSnifferSimpleRule(const std::vector<EarfcnRangeType>& range, const std::vector<uint16_t>* pciList=NULL);
    bool processStartRspMessage(const NmmToX86Protocol_SnifferStartRsp& rsp, in_addr_t peerAddr);
    bool stopSniffer();
    bool requestSnifferStatus(NmmStatus& status, bool& isRequesting, int8_t slotId = -1);
    bool configRssiThreshold(uint16_t rssi);
    bool configCell();
    void initializeSnifferInstance();
    SnifferInstance* getAvailSnifferInstance();
    SnifferInstance* getSnifferInstance(in_addr_t addr, bool getActive = true);
    SnifferInstance* getSnifferInstance(uint8_t slotId);
    SnifferInstance* getSnifferInstance(EarfcnCapacity bandSupported);
    SnifferInstance* getSnifferInstance(EarfcnCapacity bandSupported, ChinaTelecomOperator mpoperator);
    void processSnifferResult();
    void configSimulatedCell();
    void reportSnifferResultToCmd();
    void packSnifferResult(uint8_t* buffer, uint32_t& length);

    bool spiltEarfcnRange(uint8_t band, std::map<uint32_t/*band mask*/, std::vector< EarfcnRangeType > >& spiltTbl, const EarfcnRangeType& range);

    NmmResult* findStrongestRssi(std::vector<NmmResult>&);
    void generateIntraFreqNbrList(uint16_t earfcn, std::vector<uint16_t>& intraFreqNbrPciList);
    void generateInterFreqNbrList(uint16_t earfcn, std::vector<uint16_t>& interFreqList);

    SnifferManager* setRptStrategy(uint32_t);
    static const char* IPADDR_CARD1;
    static const char* IPADDR_CARD2;
    static const char* IPADDR_CARD3;
    static const char* IPADDR_CARD4;
    static const char* IPADDR_CARD5;
    static const char* IPADDR_CARD6;
    std::vector<SnifferInstance*> snifferInstanceArray_;
    std::list<SnifferInstance*> currentSnifferInstanceList_;
    std::map<uint8_t/*slot id*/, std::vector<NmmResult> > snifferResults_;

    //todo: remove duplicated
    std::vector<NmmResult> snifferResultArray_;
    SnifferState* state_;

    uint16_t configedRssiThreshold_;
    bool isAutoCfgCell_;

    enum ReportResultStrategy
    {
        RPT_RESULT_ALL = 0,
        RPT_RESULT_EXCLUDE_RSSI_NO_CELL_SEARCH = 1,
    } ;
    ReportResultStrategy rptStrategy_;
};
#endif
#define EutranTimerPtr (EutranTimer::instance())
//#define SnifferManagerPtr (SnifferManager::instance())
#define SnifferIdleStatePtr (SnifferIdleState::instance())
#define SnifferMeasuringStatePtr (SnifferMeasuringState::instance())

#endif
